package com.kgcx.common.handler;

import com.alibaba.fastjson.JSON;
import com.kgcx.common.bean.ReturnData;
import com.kgcx.common.exception.BusinessException;
import com.xiaoleilu.hutool.util.TypeUtil;
import feign.FeignException;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * feign定制解码器，可方便在编写feign的client时，不再声明ReturnData作为返回对象
 * 可直接用data的实际类型作为返回对象，实际返回的响应结果会在此解码器中处理成非ReturnData类型
 * 这样调用外部web接口就像调用内部方法一样方便，不需要判断返回值是否为0和getData等操作。
 *
 * @author 吴刚林
 * @date 2018/4/4
 */
@Slf4j
public class CustSpringDecoder extends SpringDecoder {
    public CustSpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
        super(messageConverters);
    }

    @Override
    public Object decode(Response response, Type type) throws IOException, FeignException {
        String msg = "";
        //如果在client声明为RetuenData时，就直接返回
        if (ReturnData.class.equals(TypeUtil.getClass(type))) {
            return super.decode(response, type);
        } else {
            /**
             *如果client声明的返回类型是非RetuenData，则需要此解码器定制操作了
             */
            Type t = ParameterizedTypeImpl.make(ReturnData.class, new Type[]{type}, null);
            //还是按照ReturnData作为返回值来json解码
            Object decode = super.decode(response, t);
            if (decode instanceof ReturnData) {
                ReturnData rd = (ReturnData) decode;
                if (rd.success()) {
                    //然后取实际数据返回，对应了client的声明返回类型
                    return rd.getData();
                }
                msg = rd.getCode() + "-" + rd.getMsg();
            }
            log.error("调用外部服务接口失败，response:" + JSON.toJSONString(decode) + ",type:" + type);
            throw new BusinessException("-1", msg);
        }
    }
}
